/*
   Copyright (c) [2023] [魔凤啸天]
   [MFUI] is licensed under Mulan PSL v2.
   You can use this software according to the terms and conditions of the Mulan PSL v2. 
   You may obtain a copy of Mulan PSL v2 at:
            http://license.coscl.org.cn/MulanPSL2 
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
   See the Mulan PSL v2 for more details.  
*/
#include "button.hpp"

namespace MFUI{
	Button::Button():state(state_released),entered(false){}
	Button::Button(std::initializer_list<Node*>& children):CacheNode(children){}
	Button::State Button::getstate()const{return state;}
	void Button::pressed(Window* w,SDL_FPoint& p){}
	void Button::released(Window* w,SDL_FPoint& p){}
	void Button::mouseentered(Window* w){}
	void Button::mouseexited(Window* w){}
	void Button::mousemove(Window* w,SDL_FPoint p){}
	Button::~Button(){}
	void Button::onadd(Window* w){
		w->connect(SDL_MOUSEMOTION,this,(Window::EventCallback)mousemotioncallback);
		w->connect(SDL_MOUSEBUTTONDOWN,this,(Window::EventCallback)mousebuttondowncallback);
		w->connect(SDL_MOUSEBUTTONUP,this,(Window::EventCallback)mousebuttonupcallback);
	}
	void Button::onremove(Window* w){
		if(entered){
			entered=false;
			state=state_released;
			mouseexited(w);
		}
		Node::onremove(w);
		w->disconnect(SDL_MOUSEMOTION,this);
		w->disconnect(SDL_MOUSEBUTTONDOWN,this);
		w->disconnect(SDL_MOUSEBUTTONUP,this);
	}
	void Button::mousebuttondowncallback(Window* w,Button* btn,SDL_Event* e){
		auto& b=e->button;
		auto& r=btn->rect;
		if(r.x<=b.x&&b.x<=r.x+r.w&&r.y<=b.y&&b.y<=r.y+r.h){
			btn->state=state_pressed;
			w->setfocus(btn);
			btn->_pressed(w,{(float)b.x,(float)b.y});
		}
	}
	bool Button::ismouseentered(){return entered;}
	void Button::mousebuttonupcallback(Window* w,Button* btn,SDL_Event* e){
		auto& b=e->button;
		auto& r=btn->rect;
		if(r.x>b.x||b.x>r.x+r.w||r.y>b.y||b.y>r.y+r.h)w->unsetfocus(btn);
		if(btn->state==state_pressed){
			if(btn->entered)btn->state=state_on;else btn->state=state_released;
			btn->_released(w,{(float)b.x,(float)b.y});
			return;
		}
		if(btn->entered){
			btn->state=state_on;
			return;
		}
		btn->state=state_released;
	}
	void Button::_pressed(Window* w,SDL_FPoint p){pressed(w,p);}
	void Button::_released(Window* w,SDL_FPoint p){released(w,p);}
	void Button::mousemotioncallback(Window* w,Button* btn,SDL_Event* e){
		auto& b=e->motion;
		auto& r=btn->rect;
		if(r.x<=b.x&&b.x<=r.x+r.w&&r.y<=b.y&&b.y<=r.y+r.h){
			if(!btn->entered){
				btn->entered=true;
				if(btn->state==state_released)btn->state=state_on;
				btn->mouseentered(w);
				return;
			}
			btn->mousemove(w,{(float)b.x,(float)b.y});
			return;
		}
		if(btn->entered){
			btn->entered=false;
			if(btn->state==state_on)btn->state=state_released;
			btn->mouseexited(w);
		}
		if(btn->focused())btn->mousemove(w,{(float)b.x,(float)b.y});
	}
}